package com.jack.completablefuture;

import lombok.Getter;
import lombok.Setter;

import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Future;

/**
 * Created by zhang_j on 2019/11/26
 */
@Getter
@Setter
public class Shop {
    private Random random = new Random();
    public String name;
    private Double price;

    Shop(String name){this.name = name;}

    /**
     * CompletableFuture类自身提供了大量精巧的工厂方法
     * supplyAsync方法:接受一个生产者(Supplier)作为参数，返回一个CompletableFuture对象，
     *      该对象完成异步执行完成后会读取调用生产者方法的返回值。生产者方法会交由ForkJoinPool池中的某个执行线程运行，
     *      但你也可以使用supplyAsync重载版本，传递第二个参数指定不同的执行线程执行生产者方法。
     * @param product
     * @return
     */
    public Future<Double> getPriceAsync(String product){
        return CompletableFuture.supplyAsync(() -> calculatePrice(product));
    }

    /**
     * 为了让客户端能了解商店无法提供请求商品价格的原因，需要使用
     * CompletableFuture 的 completeExceptionally 方法将导致 CompletableFuture 内发生问
     * 题的异常抛出。
     * @param product
     * @return
     */
//    public Future<Double> getPriceAsync(String product){
//        CompletableFuture<Double> futurePrice = new CompletableFuture<>();
//        new Thread(()->{
//            try {
//                double price = calculatePrice(product);
//                futurePrice.complete(price);
//            } catch (Exception ex) {
//                futurePrice.completeExceptionally(ex);
//            }
//        }).start();
//        return futurePrice;
//    }

    public Double getPrice(String product){
        return calculatePrice(product);
    }

    public static void delay(){
        try{
            Thread.sleep(1000L);
        }catch (InterruptedException e){
            throw new RuntimeException();
        }
    }

    private Double calculatePrice(String product){
        delay();
        return random.nextDouble() * product.charAt(0) + product.charAt(1);
    }
}
